package config

import (
	"github.com/urfave/cli/v2"
	"os"
	"strings"
)

// 命令行参数解析
func parseArgs() error {
	app := &cli.App{
		Name:    Config.Name,
		Version: Config.Version,
		Usage:   "Simple proxy service",
		UsageText: "proxy [global options] command [command options]\n" +
			"proxy socks\n" +
			"proxy --daemon http\n" +
			"proxy --dns 223.5.5.5 --listen 127.0.0.1 --port 8080 http --acl acl.txt\n" +
			"proxy --dns 223.5.5.5 --listen 127.0.0.1 --port 8080 socks --users_file user_list.txt",
		Flags: []cli.Flag{
			&cli.StringFlag{Name: "listen", Aliases: []string{"l"}, Value: Config.ListenAddr, Destination: &Config.ListenAddr, Usage: "listening address"},
			&cli.IntFlag{Name: "port", Aliases: []string{"p"}, Value: Config.Port, Destination: &Config.Port, Usage: "listening port"},
			&cli.StringFlag{Name: "dns", Aliases: []string{"d"}, Destination: &Config.DnsServer, Usage: "DNS server address"},
			&cli.BoolFlag{Name: "daemon", Destination: &Config.Daemon, Usage: "daemon mode"},
			&cli.BoolFlag{Name: "debug", Destination: &Config.Debug, Usage: "Debug mode"},
			&cli.StringFlag{Name: "log", Destination: &Config.Log, Usage: "log file"},
		},
	}
	app.Commands = []*cli.Command{
		{
			Name:  Config.Tcp.Name,
			Usage: "tcp proxy mode",
			Flags: []cli.Flag{
				&cli.IntFlag{Name: "timeout", Aliases: []string{"t"}, Value: 30, Destination: &Config.Tcp.Timeout, Usage: "tcp timeout"},
				&cli.StringFlag{Name: "target", Required: true, Destination: &Config.Tcp.Target, Usage: "tcp target server (example: --target 8.8.8.8:8080)"},
			},
			Action: func(c *cli.Context) error {
				Config.ProxyMode = Config.Tcp.Name
				return nil
			},
		},
		{
			Name:  Config.Http.Name,
			Usage: "http(s) proxy mode",
			Flags: []cli.Flag{
				&cli.StringFlag{Name: "user", Aliases: []string{"u"}, Destination: &Config.Http.AuthUser, Usage: "Proxy server auth account"},
				&cli.StringFlag{Name: "password", Aliases: []string{"p"}, Destination: &Config.Http.AuthPassword, Usage: "Proxy server auth password"},
				&cli.StringFlag{Name: "users_file", Aliases: []string{"f"}, Destination: &Config.Http.AuthFilePath, Usage: "proxy server auth User ListFile"},
				&cli.StringFlag{Name: "acl", Destination: &Config.Http.AclFilePath, Usage: "http ACL ListFile"},
			},
			Action: func(c *cli.Context) error {
				Config.ProxyMode = Config.Http.Name
				return nil
			},
		},
		{
			Name:  Config.Socks.Name,
			Usage: "socks mode",
			Flags: []cli.Flag{
				&cli.StringFlag{Name: "user", Aliases: []string{"u"}, Destination: &Config.Socks.AuthUser, Usage: "socks auth account"},
				&cli.StringFlag{Name: "password", Aliases: []string{"p"}, Destination: &Config.Socks.AuthPassword, Usage: "socks auth password"},
				&cli.StringFlag{Name: "users_file", Aliases: []string{"f"}, Destination: &Config.Socks.AuthFilePath, Usage: "auth User ListFile"},
				&cli.StringFlag{Name: "acl", Destination: &Config.Socks.AclFilePath, Usage: "socks ACL ListFile"},
			},
			Action: func(c *cli.Context) error {
				Config.ProxyMode = Config.Socks.Name
				return nil
			},
		},
	}

	return app.Run(os.Args)
}

func init() {
	if len(os.Args) > 1 && strings.HasPrefix(os.Args[1], "-test") {
		// 执行单元测试, 不解析命令行参数
		return
	}
	if err := parseArgs(); err != nil || Config.ProxyMode == "" {
		// 参数解析错误, 或未指定代理模式, 退出执行
		os.Exit(0)
	}
}
